package cn.batch.daemon.loadBatch;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import cn.batch.daemon.Configuration;
import cn.batch.daemon.hibernate.bean.BatchRiskData;
import cn.batch.daemon.jdbc.RiskWarningStore;
import cn.batch.daemon.procWebservice.bean.HtmlParseListRequest;
import cn.batch.daemon.procWebservice.bean.HtmlParseRequest;
import cn.batch.daemon.procWebservice.bean.HtmlParseResponse;
import cn.batch.daemon.procWebservice.client.HtmlParseHandlerBatchService_Client;
import cn.batch.daemon.service.RiskWarningService;
import cn.batch.daemon.util.Assert;

/**
 * 发送客户信息到人行。
 * 
 * @author MyUser
 * 
 */
public class RiskWarnMonthSendInfoFromRiskData  {
	private static final Log logger = LogFactory
			.getLog(RiskWarnMonthSendInfoFromRiskData.class);

	// private static final String SEARCH_SLEEPTIME = "riskWarning.sleeptime";
	// private static final String ERROR_SLEEPTIME =
	// "riskWarning.errorSleeptime";
	private static final String DEFAULT_BATCH_SIZE = "riskWarning.batch.size"; // 默认每个批次发送客户的数量
	//
	// private static final int DEFAULT_SLEEPTIME = 5000;

	// private int sleepTime;
	// private int errorSleepTime;
	private int batchSize; // 批次大小

	private String batchDate;
	//private String flagDate;
	private boolean initialized = false;

	private RiskWarningService riskWarningService;

	private Configuration config;

	private ApplicationContext ctx;

	private static String loanFlag = "1234567ZDG";

	/**
	 * @param config
	 */
	public RiskWarnMonthSendInfoFromRiskData(Configuration config) {
		super();
		this.config = config;
	}

	/**
	 * 初始化
	 */
	public void initialize() {
		if (ctx == null) {
			ctx = new ClassPathXmlApplicationContext(
					new String[] { "applicationContext*.xml" });
		}

		riskWarningService = (RiskWarningService) ctx
				.getBean("riskWarningService");
		batchSize = config.getSetting(DEFAULT_BATCH_SIZE, 1000);

		initialized = true;
	}

	public void run() {
		
		initialize();
		Assert.state(initialized, "必须初始化完成才能运行");
		
		
		//TaskMissionBean tmb = new TaskMissionBean();
		// while (true) {
		try {
			/*logger.info("开始执行风险预警客户征信数据检核及查询发送批处理任务，批次日期为" + batchDate);

			// 先按批次号删除待处理客户数据表中的数据，以免数据重复
			BatchRiskData dData = new BatchRiskData();
			dData.setBatchNo(batchDate);
			List<BatchRiskData> idList = riskWarningService
					.queryBatchRiskData(dData);
			// 根据主表ID,删除子表数据
			for (BatchRiskData batchRiskData : idList) {
				riskWarningService.deleteBatchRiskData(batchRiskData);
			}

			// 记录操作
			logger.info("*******************开始调用风险预警(按月)人行征信数据检核规则***********************");
			tmb.setBatch_no(batchDate); // 批次号
			tmb.setMissionTyp(TaskMissionType.PRCQ); // 任务类型
			tmb.setDisposeStartTm(new Timestamp(System.currentTimeMillis())); // 起始时间
			tmb.setMissionSts(MissionSts.DISPOSING); // 任务状态 执行中
			tmb.setRemark("开始调用风险预警(按月)人行征信数据检核规则。"); // 备注
			MessionTaskStore.updateTaskMissionStatus(tmb);
			// 获取客户数据
			List<BatchRiskData> batchRiskDataList = RiskWarningStore
					.getRiskMonthCustInfo(DateUtil.zhDateString(batchDate,
							"yyyyMMdd", "yyyy-MM-dd"));
			RiskWarningServer server = (RiskWarningServer) RiskWarningServer
					.createServer(ServerFileConfig.SERVER_PATH);
			int cheakProcNum = 0;
			int noProcNum = 0;
			for (BatchRiskData batchRiskData : batchRiskDataList) {
				// 查询客户的征信查询时间、当前贷款是否逾期
				PbocSummary ps = new PbocSummary();
				ps.setQuerierCertType(batchRiskData.getPaperkind());
				ps.setQuerierCertNo(batchRiskData.getPaperid());
				ps.setQuerierName(batchRiskData.getCustname());
				List<PbocSummary> pl = riskWarningService.queryByExample(ps);
				if (pl.size() <= 0) {
					batchRiskData.setProcFlag("1");
					batchRiskData.setBatchNo(batchDate);
					noProcNum++;
				} else {
					PbocSummary checkP = (PbocSummary) pl.get(0);
					Date queryDate = checkP.getQueryTime();
					@SuppressWarnings("rawtypes")
					Set pbocLoanSummaries = checkP.getPbocLoanSummaries();
					@SuppressWarnings("rawtypes")
					Iterator itLoan = pbocLoanSummaries.iterator();
					int loanNum = 0;
					while (itLoan.hasNext()) {
						PbocLoanSummary pbocLoanSummary = (PbocLoanSummary) itLoan
								.next();
						String str = pbocLoanSummary.getPaymentStatusM24();
						if (str != null) {
							if (!str.trim().equals("")
									&& loanFlag.contains(String.valueOf(str
											.charAt(str.length() - 1))))
								loanNum++;
						}
					}
					// 组装风险预警(按月)规则一的xml
					String checkXml = makeXML(batchRiskData, queryDate, loanNum);
					String checkXml2 = makeXML2(batchRiskData, loanNum); 
					
					// 调用人行征信数据检核规则
					String checkS = server.checkPboc(checkXml);
					// 调用规则，获得结果
					String resultXmlStr = server.checkPboc2(checkXml2);
					
					// 检核字段PBOC_QUERY_FLAG
					if (readRiskWarningXml(checkS) || readRiskWarningXml(resultXmlStr)) {
						// 不需要查询客户的人行征信数据
						batchRiskData.setProcFlag("0");
						batchRiskData.setBatchNo(batchDate);
					} else {
						// 需要查询客户的人行征信数据 （触发规则）
						batchRiskData.setProcFlag("1");
						batchRiskData.setBatchNo(batchDate);
						cheakProcNum++;
					}
				}
				// 将客户数据入库，供风险预警(按月)批处理使用
				riskWarningService.saveBatchRiskData(batchRiskData);
			}
			server.shutdown();
			logger.info("查无人行征信数据客户数：" + noProcNum);
			logger.info("触发风险预警(按月)人行征信数据检核规则客户数：" + cheakProcNum);
			logger.info("需要进行人行征信数据查询客户数共计：" + (noProcNum + cheakProcNum));
			logger.info("*******************结束调用风险预警(按月)人行征信数据检核规则***********************");
			if ((noProcNum + cheakProcNum) > 0) {*/
				// 重新查询规则调用后的待处理客户数据
				List<HtmlParseRequest> requestVoList = RiskWarningStore
						.getRiskMonthData(batchDate);
				// 分批发送给人行
				int requestVoSize = requestVoList.size();
				int batchNum = requestVoSize / batchSize;
				int lastBatchNum = requestVoSize % batchSize;
				if (lastBatchNum > 0) {
					batchNum++;
				}

				logger.info("开始调用人行征信接口，发送数据。");
				// 记录日志到数据库
				/*tmb.setDisposeStartTm(new Timestamp(System.currentTimeMillis())); // 起始时间
				tmb.setMissionSts(MissionSts.DISPOSING); // 任务状态 执行中
				tmb.setRemark("开始调用人行征信接口，发送数据。"); // 备注
				MessionTaskStore.updateTaskMissionStatus(tmb);*/

				HtmlParseListRequest listRequest = new HtmlParseListRequest();
				List<HtmlParseRequest> tempList = null;
				int fromIndex, toIndex, successNum = 0, actualBatchSize;
				long startTimeMillis;
				for (int i = 0; i < batchNum; i++) {
					fromIndex = i * batchSize;
					toIndex = (i == batchNum - 1) ? fromIndex + lastBatchNum
							: fromIndex + batchSize;
					tempList = requestVoList.subList(fromIndex, toIndex);
					listRequest.setHtmlParseRequestList(tempList);
					HtmlParseResponse response = null;
					actualBatchSize = tempList.size();
					logger.info(new StringBuilder(90).append("正在发送批次  ")
							.append(i + 1).append("  ，客户数量   ")
							.append(actualBatchSize).append("  ; 总批次数  ")
							.append(batchNum).append("  ，总客户数  ")
							.append(requestVoSize));
					// 调用人行征信接口,传递客户数据,并获得响应
					startTimeMillis = System.currentTimeMillis();
					// response =
					// ProcWebserviceClient.getProcResult(listRequest);
					response = HtmlParseHandlerBatchService_Client
							.getProcResult(listRequest);
					logger.debug("调用耗时："
							+ ((System.currentTimeMillis() - startTimeMillis) / 1000)
							+ "秒");
					  /*1//成功
						2//失败
						3//请求记录错误
						4//请求记录重复
						5//查询失败
						6//解析失败
						7//处理异常
						8//接收成功待处理
						9//请求报文处理中
						a//成功生成反馈报文
						X//查无此人	*/
					if (response == null || !"8".equals(response.getResultCode())) {
						logger.warn("调用人行征信接口返回失败结果：" + response.toString());
					} else {
						successNum += actualBatchSize;
						logger.info("批次  " + (i + 1) + "  发送成功。");
					}

				} // for end
				StringBuilder remark = new StringBuilder(100)
						.append("结束调用人行征信接口，发送完成。累计成功发送客户数  ")
						.append(successNum).append("  总客户数  ")
						.append(requestVoSize);
				logger.info(remark.toString());
				
				// 记录日志到数据库
				/*tmb.setDisposeEndTm(new Timestamp(System.currentTimeMillis()));
				tmb.setMissionSts(MissionSts.SUCCESS); // 任务状态
				tmb.setRemark(remark.toString()); // 备注
				MessionTaskStore.updateTaskMissionStatus(tmb);*/
			/*} else {
				logger.info("无人行征信数据及触发风险预警(按月)人行征信数据检核规则客户数为0");
				logger.info("无需进行人行征信数据查询，任务结束");
				tmb.setDisposeEndTm(new Timestamp(System.currentTimeMillis()));
				tmb.setMissionSts(MissionSts.SUCCESS); // 任务状态
				tmb.setRemark("无人行征信数据及触发风险预警(按月)人行征信数据检核规则客户数为0，无需进行人行征信数据查询"); // 备注
				MessionTaskStore.updateTaskMissionStatus(tmb);
			}*/

		} catch (Exception e) {
			/*tmb.setMissionSts(MissionSts.FAILED);
			tmb.setDisposeEndTm(new Timestamp(System.currentTimeMillis()));
			tmb.setRemark("风险预警(按月)获得客户信息或连接人行征信前置系统时失败,请联系系统管理员解决问题。");
			try {
				MessionTaskStore.updateTaskMissionStatus(tmb);
			} catch (SQLException sqle) {
				logger.error("更新任务状态信息表失败。", sqle);
			}*/
			logger.error("风险预警(按月)批量处理失败", e);
			throw new RuntimeException(e);
		}
		// } // while end
	} // run() end

	/**
	 * 将客户信息组装成blaze规则库所需的xml格式.
	 * 
	 * @param batchRiskData
	 * @param queryDate
	 * @param loanNum
	 * @return
	 */
	private String makeXML(BatchRiskData batchRiskData, Date queryDate,
			int loanNum) {
		/* 建立document对象 */
		Document document = DocumentHelper.createDocument();
		/* 建立根节点 */
		Element sqrElement = document.addElement("APPLICANTION_INFO");

		/** 创建APPLICANT_PBOC_INFO节点 */
		Element APPLICANT_PBOC_INFO = sqrElement
				.addElement("APPLICANT_PBOC_INFO");
		// 最近一次征信查询日期
		if (queryDate != null) {
			DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
			String date = format.format(queryDate);
			APPLICANT_PBOC_INFO.addAttribute("LAST_QUERY_DATE", date);
		} else {
			APPLICANT_PBOC_INFO.addAttribute("LAST_QUERY_DATE", "");
		}

		/** 创建APPLICANT_PBOC_LOAN_INFO节点 */
		Element APPLICANT_PBOC_LOAN_INFO = APPLICANT_PBOC_INFO
				.addElement("APPLICANT_PBOC_LOAN_INFO");
		// 贷款是否逾期
		if (loanNum > 0) {
			APPLICANT_PBOC_LOAN_INFO.addAttribute("LOAN_STATUS", "1");
		} else {
			APPLICANT_PBOC_LOAN_INFO.addAttribute("LOAN_STATUS", "0");
		}
		// 贷款余额
		if (batchRiskData.getLoanBalSum() != null) {
			APPLICANT_PBOC_LOAN_INFO.addAttribute("LOAN_OVERDRAFT",
					batchRiskData.getLoanBalSum().toString());
		} else {
			APPLICANT_PBOC_LOAN_INFO.addAttribute("LOAN_OVERDRAFT", "0");
		}
		/** 创建APPLICANT_LOAN_INFO子节点 */
		Element APPLICANT_LOAN_INFO = sqrElement
				.addElement("APPLICANT_LOAN_INFO");
		// 货款品种
		if (batchRiskData.getProType() != null
				&& !batchRiskData.getProType().trim().equals("")) {
			APPLICANT_LOAN_INFO.addAttribute("LOAN_CATEGORY",
					batchRiskData.getProType());
		}
		/** 创建APPLICANTION_DECISION_RESULT子节点 */
		Element APPLICANTION_DECISION_RESULT = sqrElement
				.addElement("APPLICANTION_DECISION_RESULT");
		// 评分结果
		if (batchRiskData.getAudScore() != null) {
		}
		APPLICANTION_DECISION_RESULT.addAttribute("SCORE", batchRiskData
				.getAudScore().toString());

		/** xml文件转换成String */
		String xmlString = "";
		try {
			xmlString = doc2String(document);
		} catch (IOException e) {
			logger.error("风险预警客户信息的xml文档内容转为String时出错", e);
		}
		return xmlString;
	}
	
	private String makeXML2(BatchRiskData customer, int loanNum) {
		/* 建立document对象 */
		Document document = DocumentHelper.createDocument();
		/* 建立根节点 */
		Element root = document.addElement("APPLICANTION_INFO");
		
		Element applicantInfo = root.addElement("APPLICANT_INFO");
		applicantInfo.addAttribute("EDUCATION", customer.getEducsign());
		applicantInfo.addAttribute("ANNUAL_INCOME_TY", customer.getYearPincome().toString());
		
		Element applicantLoanInfo = root.addElement("APPLICANT_LOAN_INFO");
		applicantLoanInfo.addAttribute("PAYMENT_METHOD", customer.getRetukind());
		
		root.addElement("APPLICANT_MORTGAGE_INFO");
		root.addElement("GUARANTOR_INFO");
		root.addElement("APPLICANT_SPOUSE_INFO");
		root.addElement("APPLICANT_FRAUD_INFO");
		root.addElement("APPLICANTION_DECISION_RESULT");

		/** 创建APPLICANT_PBOC_INFO节点 */
		Element applicantPbocInfo = root.addElement("APPLICANT_PBOC_INFO");
		/** 创建APPLICANT_PBOC_LOAN_INFO节点 */
		Element applicantPbocLoanInfo = applicantPbocInfo
				.addElement("APPLICANT_PBOC_LOAN_INFO");
		// 贷款是否逾期
		if (loanNum > 0) {
			applicantPbocLoanInfo.addAttribute("LOAN_STATUS", "1");
		} else {
			applicantPbocLoanInfo.addAttribute("LOAN_STATUS", "0");
		}
		// 贷款余额
		if (customer.getLoanBalSum() != null) {
			applicantPbocLoanInfo.addAttribute("LOAN_OVERDRAFT",
					customer.getLoanBalSum().toString());
		} else {
			applicantPbocLoanInfo.addAttribute("LOAN_OVERDRAFT", "0");
		}
		
		root.addElement("APPLICANT_CM_INFO");

		/** xml文件转换成String */
		String xmlString = "";
		try {
			xmlString = doc2String(document);
		} catch (IOException e) {
			logger.error("风险预警客户信息的xml文档内容转为String时出错", e);
			throw new RuntimeException(e);
		}
		return xmlString;
	}

	/** 将xml文档内容转为String */
	private String doc2String(Document document) throws IOException {
		String s = "";
		// 使用输出流来进行转化
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		// 使用GB2312编码
		OutputFormat format = new OutputFormat("  ", true, "UTF-8");
		XMLWriter writer = new XMLWriter(out, format);
		writer.write(document);
		s = out.toString("UTF-8");
		return s;
	}

	/**
	 * 读取xml文件
	 * 
	 * @param sXml
	 * @return
	 */
	private boolean readRiskWarningXml(String sXml) {
		try {
			Document doc = DocumentHelper.parseText(sXml);
			Element root = doc.getRootElement();
			Element root2 = root.element("APPLICANT_PBOC_INFO");
			// 评分分数
			String checkS = root2.attribute("PBOC_QUERY_FLAG").getValue()
					.trim();
			if ("0".equals(checkS)) {
				return true;
			}
		} catch (DocumentException e) {
			logger.error("规则库处理结果转换为xml时出错", e);
		}

		return false;
	}
	
	/**
	 * @param batchDate
	 *            the batchDate to set
	 */
	public void setBatchDate(String batchDate) {
		this.batchDate = batchDate;
	}
}
